use crate::protocol::{RedisCommand, RespValue};
use crate::storage::{Storage, StorageEngine, RedisValue};
use std::collections::HashSet;

/// SADD key member [member ...]
pub async fn sadd(storage: &Storage, command: RedisCommand) -> RespValue {
    if command.arg_count() < 2 {
        return RespValue::error("ERR wrong number of arguments for 'sadd' command");
    }

    let key = &command.args[0];
    let members = &command.args[1..];

    let mut set = match storage.get(key) {
        Some(RedisValue::Set(existing_set)) => existing_set,
        Some(_) => return RespValue::error("WRONGTYPE Operation against a key holding the wrong kind of value"),
        None => HashSet::new(),
    };

    let mut added = 0;
    for member in members {
        if set.insert(member.clone()) {
            added += 1;
        }
    }

    storage.set(key.clone(), RedisValue::Set(set), None);
    RespValue::integer(added)
}

/// SREM key member [member ...]
pub async fn srem(storage: &Storage, command: RedisCommand) -> RespValue {
    if command.arg_count() < 2 {
        return RespValue::error("ERR wrong number of arguments for 'srem' command");
    }

    let key = &command.args[0];
    let members = &command.args[1..];

    match storage.get(key) {
        Some(RedisValue::Set(mut set)) => {
            let mut removed = 0;

            for member in members {
                if set.remove(member) {
                    removed += 1;
                }
            }

            if set.is_empty() {
                storage.del(key);
            } else {
                storage.set(key.clone(), RedisValue::Set(set), None);
            }

            RespValue::integer(removed)
        }
        Some(_) => RespValue::error("WRONGTYPE Operation against a key holding the wrong kind of value"),
        None => RespValue::integer(0),
    }
}

/// SISMEMBER key member
pub async fn sismember(storage: &Storage, command: RedisCommand) -> RespValue {
    if command.arg_count() != 2 {
        return RespValue::error("ERR wrong number of arguments for 'sismember' command");
    }

    let key = &command.args[0];
    let member = &command.args[1];

    match storage.get(key) {
        Some(RedisValue::Set(set)) => {
            RespValue::integer(if set.contains(member) { 1 } else { 0 })
        }
        Some(_) => RespValue::error("WRONGTYPE Operation against a key holding the wrong kind of value"),
        None => RespValue::integer(0),
    }
}

/// SMEMBERS key
pub async fn smembers(storage: &Storage, command: RedisCommand) -> RespValue {
    if command.arg_count() != 1 {
        return RespValue::error("ERR wrong number of arguments for 'smembers' command");
    }

    let key = &command.args[0];

    match storage.get(key) {
        Some(RedisValue::Set(set)) => {
            let members: Vec<RespValue> = set.iter()
                .map(|member| RespValue::bulk_string(member.clone()))
                .collect();

            RespValue::array(members)
        }
        Some(_) => RespValue::error("WRONGTYPE Operation against a key holding the wrong kind of value"),
        None => RespValue::array(vec![]),
    }
}

/// SCARD key
pub async fn scard(storage: &Storage, command: RedisCommand) -> RespValue {
    if command.arg_count() != 1 {
        return RespValue::error("ERR wrong number of arguments for 'scard' command");
    }

    let key = &command.args[0];

    match storage.get(key) {
        Some(RedisValue::Set(set)) => RespValue::integer(set.len() as i64),
        Some(_) => RespValue::error("WRONGTYPE Operation against a key holding the wrong kind of value"),
        None => RespValue::integer(0),
    }
}